Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 <<   zurück
Visual Basic 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual Basic 2005

Visual Basic 2005
1.233 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-585-1
gp Kapitel 5 Das Klassendesign (Teil 2)
  gp 5.1 Statische Klassenkomponenten
    gp 5.1.1 Die Realisierung eines Objektzählers
    gp 5.1.2 Zugriff auf statische Komponenten
    gp 5.1.3 Statische Klassenvariable in der Klasse »Circle«
    gp 5.1.4 Klassenspezifische Methoden
    gp 5.1.5 Statische Methoden in der Klasse »Circle«
    gp 5.1.6 Statische Klasseninitialisierer
    gp 5.1.7 Zusammenfassung
  gp 5.2 Delegaten
    gp 5.2.1 Einführung in das Prinzip der Delegaten
    gp 5.2.2 Zusammenfassung der Arbeitsschritte
    gp 5.2.3 Vereinfachter Aufruf eines Delegaten
  gp 5.3 Ereignisse eines Objekts
    gp 5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle
    gp 5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger
    gp 5.3.3 Ereignisse mit Übergabeparameter
    gp 5.3.4 Die Handles-Klausel
    gp 5.3.5 Die Registrierung eines Ereignishandlers mit »AddHandler«
    gp 5.3.6 Zusammenfassung
  gp 5.4 Strukturen – eine Sonderform der Klassen
    gp 5.4.1 Die Definition einer Struktur
    gp 5.4.2 Initialisieren einer Struktur
    gp 5.4.3 Ereignisse in einer Struktur
    gp 5.4.4 Änderung der Klasse »Circle«
    gp 5.4.5 Zusammenfassung der Unterscheidungsmerkmale Klasse – Struktur
  gp 5.5 Enumerationen (Aufzählungen)
    gp 5.5.1 Alle Mitglieder einer Aufzählung durchlaufen
  gp 5.6 Referenz- und Wertetypen
    gp 5.6.1 Typumwandlung mit Boxing
    gp 5.6.2 Die Unboxing-Konvertierung
    gp 5.6.3 Zusammenfassung
  gp 5.7 Namensräume (Namespaces)
    gp 5.7.1 Zugriff auf Namespaces
    gp 5.7.2 Die »Imports«-Anweisung
    gp 5.7.3 Aliasnamen zur Vermeidung von Mehrdeutigkeiten
    gp 5.7.4 Aufrufe mit »Global« umleiten
    gp 5.7.5 Namespaces festlegen
    gp 5.7.6 Zusammenfassung


Galileo Computing

5.3 Ereignisse eines Objekts  downtop

Die meisten Objekte, mit denen wir es täglich zu tun haben, reagieren auf Anstöße von außen: Ein Auto kann hupen und fahren, eine Person gehen und sprechen. Äußere Anstöße können – projiziert auf den Programmentwurf – Methodenaufrufen gleichgesetzt werden. Ein Client verwaltet beispielsweise ein Objekt vom Typ Car und ruft die Methode Fahren auf. Daraufhin setzt sich das Auto in Bewegung – zumindest aus dem programmtechnischen Blickwinkel heraus.

Die Erfahrung des täglichen Lebens zeigt aber auch, dass Objekte auf diese Anstöße ihrerseits selbst reagieren können. Stellen Sie sich vor, Sie würden in einem Mietshaus wohnen und die Lautstärke der Stereoanlage zu hoch drehen. Wenn Sie Glück haben, werden Ihre Nachbarn das stillschweigend akzeptieren, möglicherweise werden Sie aber auch noch soeben das Klingeln an der Wohnungstür vernehmen und einem vielleicht freundlich, vielleicht auch verärgert um mehr Ruhe bettelnden Nachbarn entgegentreten.

Ein Methodenaufruf ist der Anstoß eines Clients an ein Objekt, damit dieses eine bestimmte Verhaltensweise zeigt. Die Konsequenz eines Methodenaufrufs könnte sein, dass das Objekt seinerseits beim Aufrufer eine Reaktion auslöst. Diese Reaktion lässt sich ebenfalls programmiertechnisch erfassen: Sie wird als Ereignis oder auch – mit dem englischen Begriff – als Event bezeichnet. Ereignisse spielen eine herausragende Rolle bei der Programmierung grafischer Benutzeroberflächen. Sie lassen sich so abstrahieren, dass sie als Nachrichtenverkehr zwischen einer Ereignisquelle und einem Ereignisempfänger angesehen werden können. Eine Ereignisquelle könnte beispielsweise die Schaltfläche in einem Windows-Fenster sein. Sobald der Anwender mit der Maus auf die Schaltfläche klickt, wird ein Ereignis ausgelöst, auf das der Ereignisempfänger reagieren kann, aber nicht muss.

Die Richtung eines Methodenaufrufs geht immer vom Aufrufer zum Objekt. Das Objekt führt danach die Methode aus. Die Richtung eines Ereignisses ist genau entgegengesetzt: Sie geht vom Objekt zurück zum Aufrufer und hier zu einer Methode, dem Ereignisempfänger. Unter diesem Blickwinkel betrachtet ruft ein Objekt als Ereignisquelle eine ihm bekannte Methode im Client, dem Ereignisempfänger, auf.

Der Zeitpunkt der Ereignisauslösung ist im Code eines Objekts festgelegt. Das Besondere an einem Event ist, dass der Ereignisempfänger auf die Auslösung ganz individuell reagieren kann, sie unter Umständen sogar einfach ignoriert.


Galileo Computing

5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle  downtop

Die theoretische Betrachtung eines Ereignisses soll nun an einem praktischen Beispiel gezeigt werden. Erinnern wir uns dazu zunächst an die aktuelle Implementierung der Eigenschaftsmethode Radius in der Circle-Klasse:


Public Property Radius() As Double
Get
Return dblRadius
End Get
Set(ByVal Value As Double)
If Value >= 0 Then
dblRadius = Value
Else
Console.WriteLine("Unzulässiger Wert.")
End If
End Set
End Property

Uns interessiert insbesondere der Set-Accessor und dort wiederum das Verhalten der Methode, wenn der Eigenschaft ein negativer Wert übergeben wird. Nach dem derzeitigen Stand führt das zu einer Ausgabe an der Konsole.

Die Implementierung funktioniert tadellos, unterliegt jedoch einer Einschränkung: Der Client muss die Nachricht entgegennehmen – ob er will oder nicht. Anstatt an der Konsole immer nur dieselbe, gleich lautende Meldung anzuzeigen, könnte das Circle-Objekt im Client eine Methode aufrufen. Das Objekt wird in diesem Moment aktiv, denn es löst ein Ereignis aus. Der ursprüngliche Methodenaufrufer kann als Ereignisempfänger auf das Ereignis reagieren, indem in ihm eine bestimmte Methode mit einem vom Client gewünschten Verhalten ausgeführt wird.

Bisher hatten wir es immer mit der Aufrufrichtung ausgehend von einem Client zu einem Objekt zu tun. Ein Ereignis dreht diese Richtung um. Um die Wirkungsweise der Ereignisse besser zu verstehen, wollen wir nun die Klasse Circle um ein solches Ereignis erweitern und es MeasureError nennen.

Der Programmablauf bis zu einer eventuellen Ereignisauslösung würde wie folgt aussehen:

1. Der Benutzer, auch als Client bezeichnet, erzeugt ein Objekt der Klasse Circle und weist der Eigenschaft Radius einen unzulässigen Wert zu.
       
2. In der Eigenschaftsmethode wird der übergebene Wert geprüft, die Unzulässigkeit festgestellt und das Ereignis MeasureError ausgelöst mit der Folge, dass im Client nach einer Methode gesucht wird, die das Ereignis behandelt.
       
3. Erklärt sich der Client bereit, das Ereignis zu behandeln, wird im Client die dem Ereignis zugeordnete Methode ausgeführt.
       

Kommen wir nun zu den Details der Ereignisimplementierung in der Ereignisquelle. Jedes Ereignis muss in der Klassendefinition bekannt gegeben werden. Die allgemeine Syntax einer Ereignisdefinition lautet wie folgt:


' Syntax der Ereignisdefinition
[Zugriffsmodifizierer] Event Bezeichner As Typ

Dem optionalen Zugriffsmodifizierer (der Standard ist Public) folgt die Anweisung Event, dann wird der Bezeichner des Ereignisses angegeben, zum Schluss der Typ des Delegaten. Die Definition unseres Ereignisses erfolgt auf Klassenebene und könnte wie folgt lauten:


Public Event MeasureError As MeasureErrorEventHandler

Diese Variante verlangt natürlich, dass der Delegat bereits definiert ist, beispielsweise mit


Public Delegate Sub MeasureErrorEventHandler()

Sie können auch die folgende Kurzschreibweise benutzen und dann auf die Definition eines Delegaten verzichten:


Public Event MeasureError()

Nun stellt die Klasse Circle den gewünschten Event bereit, und es muss nur noch zum Ausdruck gebracht werden, wann er im Ereignisempfänger ausgelöst wird. Dazu ändern wir die Eigenschaftsmethode Radius wie folgt:


Public Property Radius() As Double
Get
Return dblRadius
End Get
Set(ByVal Value As Double)
If Value >= 0 Then
dblRadius = Value
Else
RaiseEvent MeasureError()
End If
End Set
End Property

Die ursprüngliche Codezeile zur Ausgabe an der Eingabeaufforderung wird durch die Anweisung RaiseEvent unter Angabe des auszulösenden Ereignisses ersetzt. Damit ist die Klassenimplementierung schon vollständig, um der Anforderung zu genügen.

Übergibt der Client der Eigenschaft Radius nun einen Wert, welcher der Bedingung


Radius < 0

entspricht, wird die RaiseEvent-Anweisung dazu führen, das Ereignis MeasureError im Benutzer auszulösen.


Galileo Computing

5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger  downtop

Damit ein Client ein von einem Objekt ausgelöstes Ereignis empfängt, sind zwei Voraussetzungen im Zusammenhang mit der Deklaration der Objektvariablen zu erfüllen:

1. Die Referenz auf das Objekt, dessen Ereignisse behandelt werden sollen, muss global deklariert sein und kann daher niemals lokal in einer Methode erfolgen.
       
2. In der Deklaration muss das Schlüsselwort WithEvents angegeben werden.
       

Betrachten Sie das folgende Codefragment, das den genannten Bedingungen genügt.


Class ClassA
Private WithEvents obj As Circle
Sub Main()
obj = New Circle()
' Anweisungen
End Sub
End Class

Damit ist die notwendige Vorarbeit geleistet. Es muss nun noch der Ereignishandler syntaktisch korrekt definiert werden. Sie können diesen natürlich nach festgelegten Kriterien manuell schreiben, aber der Code-Editor der Entwicklungsumgebung leistet in diesem Punkt wertvolle Unterstützung, die auch in Anspruch genommen werden sollte.

Im oberen Teil des Code-Editors befinden sich zwei Drop-down-Listenfelder (siehe Abbildung 5.1). Das linke listet alle in der Quellcodedatei definierten Klassen, Module und Strukturen auf, im rechten die zu der Auswahl in der linken Liste zugehörigen Methoden. Wird in beiden Listenfeldern jeweils eine bestimmte Auswahl getroffen, springt der Eingabecursor in den Quellcode der gewählten Elementfunktion. Damit ist auch die Aufgabe der Listenfelder klar umrissen: Sie dienen der Navigationsunterstützung.

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 5.1     Der Code-Editor nach der Auswahl des klassenspezifischen Ereignisses

Eine mit WithEvents deklarierte Objektvariable wird ebenfalls im linken Listenfeld aufgeführt. Wählen Sie ein solches Element, können Sie im rechten Listenfeld eines der vom Objekt veröffentlichten Ereignisse selektieren. Haben Sie beispielsweise in einer Klasse oder einem Modul ein Objekt vom Typ der Klasse Circle deklariert, wird der Event MeasureError in der rechten Liste angezeigt. Interessant ist die Unterstützung der Entwicklungsumgebung, die nach der Wahl des gewünschten Ereignisses in der rechten Drop-down-Liste automatisch den syntaktisch korrekten Ereignishandler generiert:


Public Sub kreis_MeasureError() Handles kreis.MeasureError
End Sub

Die Definition eines Ereignishandlers mit Sub macht die nahe Verwandtschaft zu einer herkömmlichen Methode ohne Rückgabewert deutlich. Der Bezeichner setzt sich standardmäßig aus dem Namen des konkreten Objekts, das den Event auslöst (hier: kreis), und dem Namen des Ereignisses in der Klassendefinition zusammen. Beide werden durch einen Unterstrich voneinander getrennt. In unserem Beispiel wird die leere Parameterliste durch die runden Klammern angedeutet. Wie Sie bereits wissen, können bei der Auslösung des Events auch Parameter eine Rolle spielen, deshalb wird auch eine Parameterliste erzeugt, die im Beispiel oben leer ist. Hinter der Parameterliste besagt die Handles-Klausel, welches oder welche Ereignisse von der Methode bedient werden. Wir werden auf die Parameterliste und die Handles-Klausel in den folgenden beiden Abschnitten noch näher eingehen

Fassen wir noch einmal zusammen, was zu der Auslösung eines Events führt:

1. Auf Klassenebene wird eine Objektvariable deklariert. In Kenntnis davon, dass das Objekt in der Lage ist, Events in bestimmten Situationen auszulösen, wird die Objektreferenz mit dem Schlüsselwort WithEvents deklariert.
       
2. Bei der Zuweisung eines Wertes an die Eigenschaft Radius überprüft die Eigenschaftsmethode die Zulässigkeit. Unter der Bedingung, dass der Wert kleiner null ist, führt die Anweisung RaiseEvent dazu, eine dem Objekt namentlich bekannte Methode im Client aufzurufen. Dieser Vorgang wird als Ereignisauslösung bezeichnet.
       
3. Enthält die Ereignisprozedur im Ereignisempfänger Programmcode, wird dieser ausgeführt und nach der Beendigung die Kontrolle an den Ereignisauslöser zurückgegeben.
       

Wie sich der Ereignisempfänger verhält, ob er die Ereignisauslösung ignoriert oder darauf individuell reagiert, bleibt ihm selbst überlassen. Angenommen, der Radius des Kreisobjekts soll in diesem Fall auf den benutzerdefinierten Standardwert null gesetzt werden, könnte im Client das Ereignis wie folgt ergänzt werden:


Public Sub kreis_MeasureError() Handles kreis.MeasureError
kreis.Radius = 0
End Sub

Diese Lösung ist sicherlich einfach, lässt aber andererseits dem Anwender auch keine Chance zu einer neuerlichen, dann vielleicht korrekten Wertzuweisung. Diese Einschränkung soll im folgenden Codefragment aufgehoben werden:


Public Sub kreis_MeasureError() Handles kreis.MeasureError
Console.WriteLine("Unzulässiger negativer Radius.")
Console.Write("Neueingabe: ")
kreis.Radius = Console.ReadLine()
End Sub

Der Anwender wird dazu aufgefordert, dem Kreisobjekt einen Radius größer oder gleich Null zuzuweisen. Gibt er erneut einen negativen Wert ein, wird das Ereignis MeasureError noch einmal ausgelöst – und zwar so lange, bis eine zulässige Eingabe erfolgt. Das ähnelt sehr stark einer Endlosschleife, aus der es kein Entkommen mehr gibt, obwohl hier der Weg aus dem Kreislauf durch die Eingabe eines positiven Werts möglich ist. In der Praxis sollte an dieser Stelle wohl auch noch eine weitere Möglichkeit des vorzeitigen Ausstiegs vorgesehen werden.


Galileo Computing

5.3.3 Ereignisse mit Übergabeparameter  downtop

Der Schlüssel zu einer optimalen Lösung liegt schon in der Definition des Ereignisses in der Klasse: Wir erzwingen die Übergabe eines Parameters.


Public Event MeasureError(k As Circle)

Die Idee, die hinter dem Parameter steckt, ist, dem Ereignisempfänger über diesen Parameter die Referenz auf das ereignisauslösende Objekt zu übergeben. Darüber kann der Radius erneut festgelegt werden.

Die Ergänzung der verbesserten Ereignisdefinition muss nun noch im Set-Accessor berücksichtigt werden:


Set(ByVal Value As Double)
If Value >= 0 Then
dblRadius = Value
Else
RaiseEvent MeasureError(Me)
End If
End Set

Wird die Set-Unterprozedur aufgerufen, erfolgt auch weiterhin zuerst eine Gültigkeitsüberprüfung. Fällt diese negativ aus, weil im impliziten Parameter ein Wert kleiner null enthalten ist, wird das Ereignis MeasureError im Benutzer ausgelöst. Dabei wird dem Ereignisempfänger mit Me die Referenz auf das Objekt mitgeliefert, welches das Ereignis verursacht hat. Im Ereignishandler kann die übergebene Referenz benutzt werden, um der Eigenschaft Radius nun endlich einen gültigen Wert zuzuweisen.


Module Module1
Dim WithEvents kreis As Circle
Sub Main()
kreis = New Circle()
kreis.Radius = –2
Console.WriteLine(kreis.Radius)
Console.ReadLine()
End Sub
Private Sub kreis_MeasureError(ByVal k As Circle) _
Handles kreis.MeasureError
Console.WriteLine("Radius {0} unzulässig.", k.Radius)
Console.Write("Neueingabe: ")
k.Radius = Console.ReadLine()
End Sub
End Module


Galileo Computing

5.3.4 Die Handles-Klausel  downtop

Sie haben in den letzten Abschnitten gesehen, wie sich der Name eines Ereignishandlers aus dem Bezeichner der Objektvariablen und dem Bezeichner des Ereignisses, getrennt durch einen Unterstrich, zusammensetzt, beispielsweise:


Public Sub kreis_MeasureError(k As Circle) _
Handles kreis.MeasureError

Die sich der Parameterliste anschließende Handles-Anweisung haben wir bisher noch nicht betrachtet. Wir werden uns ihr nun widmen, da sie weitere Möglichkeiten zur Reaktion auf ausgelöste Ereignisse eröffnet.

Für die Behandlung eines Ereignishandlers im Ereignisempfänger ist nicht der Bezeichner einer Methode das alles entscheidende Kriterium, sondern die Angabe hinter der Handles-Anweisung. Sie besagt, welches Ereignis vom Ereignishandler behandelt werden kann, in unserem Beispiel das Ereignis MeasureError des Objekts mit dem Namen kreis. Der Bezeichner kreis_MeasureError, der von der Entwicklungsumgebung vergeben worden ist, kann beliebig geändert werden, weil nur Handles für die eindeutige Zuordnung eines Ereignishandlers zu einem Ereignis verantwortlich ist.

Sie können mit einem Ereignishandler die Events mehrerer Objekte behandeln, indem Sie die Liste hinter der Handles-Anweisung, wie im folgenden Codefragment gezeigt wird, erweitern.


Public Sub CompleteHandler() Handles kreis1.MeasureError, _
kreis2.MeasureError
...
End Sub

Diese Methode wird ausgeführt, wenn das Ereignis MeasureError entweder von Objekt kreis1 oder Objekt kreis2 ausgelöst wird.


Galileo Computing

5.3.5 Die Registrierung eines Ereignishandlers mit »AddHandler«  downtop

Es gibt noch einen zweiten Weg, der uns unter Visual Basic 2005 die Anbindung eines Ereignisses an einen Ereignishandler ermöglicht. Ermöglicht wird dies durch die Anweisung AddHandler. Der Code, der sich im Benutzer durch den Einsatz von AddHandler ändert, zeigt das folgende Codefragment.


Module Module1
Sub Main()
Dim kreis As New Circle
AddHandler kreis.MeasureError, AddressOf kreis_MeasureError
kreis.Radius = –3
Console.ReadLine()
End Sub
Private Sub kreis_MeasureError(ByVal k As Circle)
Console.WriteLine("Radius ist nicht zugelassen.")
Console.Write("Neueingabe: ")
k.Radius = Console.ReadLine()
End Sub
End Module

AddHandler bindet das Ereignis eines Objekts an eine bestimmte Methode. Im ersten Argument des Statements werden dabei das Objekt und das Ereignis aufgeführt, dessen Auslösung behandelt werden soll. Im zweiten Argument wird hinter AddressOf die aufzurufende Methode genannt, wenn das im ersten Argument bekannt gegebene Ereignis im Objekt ausgelöst wird. Die allgemeine Syntax lautet:


AddHandler <Objekt>.<Ereignis>, AddressOf <Objekt>.<Methodenname>

Schauen Sie sich den Code oben noch einmal genau an. Interessant ist die Tatsache, dass es nun keine Handles-Klausel mehr gibt, die das Ereignis statisch an die Methode bindet, sondern dass die Bindung nun im Programmcode erfolgt. Zudem taucht im Programmcode keine WithEvents-Anweisung mehr auf.


Um ein Ereignis statisch mit der Handles-Klausel an eine Prozedur zu binden, ist die Deklaration einer Objektvariablen mit dem WithEvents-Statement auf Klassenebene Voraussetzung. Solche Bindungen sind statisch. Bei der dynamischen Bindung mit AddHandler kann auf WithEvents verzichtet werden. Zudem darf die Objektvariable innerhalb einer Methode deklariert sein.


Die Bindung mit AddHandler ist ausgesprochen flexibel, denn sie kann auch wieder gelöst werden. Dazu dient die Anweisung RemoveHandler, deren Syntax identisch mit der von AddHandler ist.


RemoveHandler kreis.MeasureError, AddressOf kreis_MeasureError

Kommt es nun zu einer Auslösung des Ereignisses MeasureError des Objekts kreis, wird das Ereignis keinen Abnehmer mehr finden.


Galileo Computing

5.3.6 Zusammenfassung  toptop

gp  Die Richtung eines herkömmlichen Methodenaufrufs geht von einem Objektnutzer zum Objekt. Eine Benachrichtigung, die das Objekt an seinen Aufrufer, den Ereignisempfänger, schickt, wird als Ereignis bezeichnet.
gp  Ein Ereignis wird mit dem Schlüsselwort Event definiert. Wird auf die Angabe des Zugriffsmodifizierers verzichtet, gilt dieser standardmäßig als Public.
gp  Mit RaiseEvent unter der Angabe des Bezeichners wird die Anweisung gegeben, im Ereignisempfänger das Ereignis auszulösen.
gp  Damit der Ereignisempfänger in der Lage ist, ein ausgelöstes Ereignis zu behandeln, muss die Objektvariable im Allgemeinteil der Klasse oder des Moduls zusammen mit dem Schlüsselwort WithEvents deklariert sein.
gp  Einem potenziellen Ereignishandler werden durch das Anhängen der Handles-Klausel das Objekt und das Ereignis angegeben, dem der Ereignishandler zugeordnet wird.
gp  Hinter der Handles-Klausel können mehrere Ereignisse getrennt durch ein Komma aufgelistet werden. Die Methode wird danach immer dann ausgeführt, sobald eines der angegebenen Ereignisse ausgelöst wird.
gp  Mit AddHandler können Ereignisse dynamisch an eine Methode gebunden werden. Die Objektvariable darf dabei lokal deklariert sein. Eine mit AddHandler eingeleitete Bindung kann mit RemoveHandler wieder aufgehoben werden.
 <<   zurück
  
  Zum Katalog
Zum Katalog: Visual Basic 2005
Visual Basic 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Visual C# 2005






 Visual C# 2005


Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Das Programmierhandbuch SQL Server 2005






 Das Programmier-
 handbuch
 SQL Server 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2007
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de